package org.xiezc.servlet;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;

import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.xiezc.annotation.Inject;

/**
 * 在构造方法中加上 根据注解从spring中获得对象赋予注解的字段
 * 
 * @author xiezc
 *
 */
@SuppressWarnings("serial")
public class MyHttpServlet extends HttpServlet {
	
	/**
	 * 根据注解从spring中取得值赋予@Inject注解的字段
	 */
	@Override
	public void init() throws ServletException {
		super.init();
		// 获得所有的属性
		Field[] fields = this.getClass().getDeclaredFields();
		// 遍历属性
		for (Field field : fields) {
			// 判断属性中是否有Inject注解
			if (field.isAnnotationPresent(Inject.class)) {
				try {
					// 获得spring的容器
					ApplicationContext applicationContext = WebApplicationContextUtils
							.getWebApplicationContext(getServletContext());
					// 获得注解对象
					Inject Inject = field.getAnnotation(Inject.class);
					// 获得注解值
					String className = Inject.value();
					// 获得属性的名称（名称不是类型）
					String fieldName = field.getName();
					// 将首字母大写
					char[] cs = fieldName.toCharArray();
					cs[0] = Character.toUpperCase(cs[0]);
					// 获得属性的set方法名
					String fieldSetMethodName = "set" + String.valueOf(cs);
					
					
					// 获得该字段的类型
					Class<?> clazz = field.getType();
					// 根据set方法名和参数类型获得方法
					Method method = this.getClass().getMethod(fieldSetMethodName, clazz);
					// 注解值为空
					if ("".equals(className)) {
						// 获得首字母小写的字段名称
						cs[0] = Character.toLowerCase(cs[0]);
						fieldName = String.valueOf(cs);
						// 调用方法，参数是从spring中获得的
						Object fieldObj = applicationContext.getBean(fieldName);
						method.invoke(this, clazz.cast(fieldObj));
					} else {// 注解值就是spring容器中的键值
						Object fieldObj = applicationContext.getBean(className);
						method.invoke(this, clazz.cast(fieldObj));
					}
				} catch (NoSuchMethodException e) {
					e.printStackTrace();
				} catch (SecurityException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (InvocationTargetException e) {
					e.printStackTrace();
				}

			}
		}
	}

}
